package com.jplus.core.core.abstracts.defaults;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import com.jplus.core.anno.com.Qualifier;
import com.jplus.core.core.ApplicationContext;
import com.jplus.core.core.ProxyHandle;
import com.jplus.core.core.abstracts.BeanDefinitions;
import com.jplus.core.core.abstracts.BeanFactory;
import com.jplus.core.core.abstracts.FactoryBean;
import com.jplus.core.core.beans.BeanDefinition;
import com.jplus.core.core.beans.BeanKey;
import com.jplus.core.core.beans.BeanWrapper;
import com.jplus.core.core.proxys.Proxy;
import com.jplus.core.core.proxys.ProxyManager;
import com.jplus.core.core.proxys.manager.ProxyByJDK;

/**
 * 职责：获取bean对象
 * 
 * @author yuanqy
 */
public class DefaultFactoryBean extends FactoryBean {

	private ProxyHandle proxy;
	private ApplicationContext context;
	private ProxyManager jdkDefault = new ProxyByJDK();

	public DefaultFactoryBean(ApplicationContext context) {
		this.context = context;
	}

	/**
	 * load interceptors
	 */
	private void initFactoryBean(BeanDefinitions bd, BeanFactory bf) {
		proxy = new ProxyHandle(bd, bf);
		proxy.init();
	}

	/**
	 * 生成对象
	 */
	public BeanWrapper<Object> getObject(BeanDefinition bd) {
		if (proxy == null) {
			synchronized (this) {
				if (proxy == null) {
					initFactoryBean(context.getBeanDefinitions(), context.getBeanFactory());
				}
			}
		}
		BeanWrapper<Object> bw = null;
		try {
			BeanKey bk = bd.getBeanKey();
			List<BeanKey> his = proxy.getProxyList(bk);
			if (his == null) {// 如果没有代理，则直接实例
				Object instance = null;
				// 如果通过@Bean创建
				if (bd.getInstanceBean() != null && bd.getInstanceMethod() != null) {
					Object obj = context.getBean(bd.getInstanceBean());// 被@Bean注入
					Method m = bd.getInstanceMethod();
					Class<?>[] arg = m.getParameterTypes();
					Annotation[][] argAns = m.getParameterAnnotations();
					Object[] args = getParamObj(arg, argAns);
					instance = m.invoke(obj, args);
				} else {
					Constructor<?>[] cons = bk.getBeanClass().getDeclaredConstructors();
					Class<?>[] arg = cons[0].getParameterTypes();
					Annotation[][] argAns = cons[0].getParameterAnnotations();
					instance = cons[0].newInstance(getParamObj(arg, argAns));
				}
				bw = setBeanWrapper(instance, null);
			} else { // 創建代理對象
				List<Proxy> proxyList = new ArrayList<>();
				for (BeanKey beanKey : his)
					proxyList.add((Proxy) context.getBean(beanKey));
				Object proxy = null;
				if (bk.getBeanClass().isInterface())// 是接口默认使用jdk
					proxy = jdkDefault.createProxy(proxyList, bk.getBeanClass());
				else
					proxy = context.getProxyManager().createProxy(proxyList, bk.getBeanClass());
				bw = setBeanWrapper(null, proxy);
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return bw;
	}

	private <T> BeanWrapper<T> setBeanWrapper(T object, T proxy) {
		BeanWrapper<T> bw = new BeanWrapper<T>(object, proxy);
		return bw;
	}

	/**
	 * 获取参数对象集
	 */
	private Object[] getParamObj(Class<?>[] arg, Annotation[][] argAns) {
		Object[] args = new Object[arg.length];
		if (arg.length > 0) { // 有参
			for (int i = 0; i < arg.length; i++) {
				String name = null;
				Annotation[] ans = argAns[i];
				for (Annotation a : ans) {
					if (a.annotationType() == Qualifier.class) {
						name = ((Qualifier) a).value();
						break;
					}
				}
				args[i] = context.getBean(name, arg[i]);
			}
		}
		return args;
	}

}
